#include "Device/LCD1602.h"
#include "Hardware/Timer.h"

#define ControlPort P3
#define DataPort P0

#define RSbit (5)
#define RWbit (6)
#define Ebit  (4)

#define RS(x) ( (!!(x))? SetBit(ControlPort,RSbit): ClrBit(ControlPort,RSbit) );Delay(1)
#define RW(x) ( (!!(x))? SetBit(ControlPort,RWbit): ClrBit(ControlPort,RWbit) );Delay(1)
#define E(x)  ( (!!(x))? SetBit(ControlPort,Ebit) : ClrBit(ControlPort,Ebit)  );Delay(1)

#define Line1 (0x80)
#define Line2 (0x80+0x40)

typedef struct POS
{
	uint8 x;//第几个,范围0-15
	uint8 y;//第几排,范围1-2
}POS; //光标位置信息

POS m_POS;

//光标放在初始化位置
void LCD1602_PosClear()
{
	m_POS.x=0;
	m_POS.y=1;
}
//光标位置+
void LCD1602_PosAdd()
{
	if(++(m_POS.x)==16)
	{
		if(m_POS.y==1)
		{	
			m_POS.y=2;
			m_POS.x=0;
		}
		else //第2排最后了
		{
			m_POS.x=15; //一直保持最后的一个位置
		}
	}
}
//光标位置-
void LCD1602_PosSub()
{
	if(m_POS.x-- == 0)
	{
		if(m_POS.y==1) //第一排第一个
		{
			m_POS.x=0; //保持在第一个
		}
		else
		{
			m_POS.x=15;
			m_POS.y=1;
		}
	}
}

void LCD1602_SetPos(uint8 line,uint8 pos)
{
	m_POS.x=pos;
	m_POS.y=line;
}



//写数据
void LCD1602_WriteData(char ch)
{
	RS(1);
	RW(0);
	DataPort=ch;
	Delay(1);
	E(1);
	E(0);
}

//写指令
void LCD1602_WriteCmd(byte cmd)
{
	RS(0);
	RW(0);
	DataPort=cmd;
	Delay(1);
	E(1);
	E(0);
}

void LCD1602_ShowCursor(bool bShowCursor,bool bFlash)
{
	LCD1602_WriteCmd( 0xC | (((uint8)bShowCursor)<<1) | ((uint8)bFlash) );
}

void LCD1602_LockPos()
{
	if(m_POS.y==1)
		LCD1602_WriteCmd(Line1+m_POS.x);
	else if(m_POS.y==2)
		LCD1602_WriteCmd(Line2+m_POS.x);
}

void LCD1602_Init()
{
	LCD1602_WriteCmd(0x38); 		 //设置16x2显示,5x7点阵,8位数据口
	LCD1602_ShowCursor(true,false);  //设置开显示,显示光标,光标闪烁
	LCD1602_WriteCmd(0x06); 		 //设置写一个字符后光标地址+1,并且整屏不移动
	LCD1602_Cls();
}


void LCD1602_WriteString(char str[],uint8 length,uint8 line,uint8 pos)
{
	uint8 i;
	if(length<17 && length+pos<17)
	{
		LCD1602_SetCursor(line,pos);
		for(i=0;i<length;++i)
		{
			LCD1602_WriteChar(str[i]);
		}
	}
}


void LCD1602_SetCursor(uint8 line,uint8 pos)
{	
	if(pos<16)
	{
		if(line==1)
		{
			LCD1602_WriteCmd(Line1+pos);
			LCD1602_SetPos(line,pos);
		}
		else if(line==2)
		{
			LCD1602_WriteCmd(Line2+pos);
			LCD1602_SetPos(line,pos);
		}
	}
}


void LCD1602_WriteChar(char ch)
{
	LCD1602_LockPos();
	LCD1602_WriteData(ch);
	LCD1602_PosAdd();
}

void LCD1602_Cls()
{
	LCD1602_WriteCmd(0x01);
	LCD1602_PosClear();
}